///\todo upgrade

//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2011 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_CONTAINER_CAUTOVECTOR_H_
#define _BUOLA_CONTAINER_CAUTOVECTOR_H_

namespace buola {

///\addtogroup container
///@{

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/// automatic storage vector

/// Holds an array of elements of a certain type \p tType. The number of elements can be
/// specified in the constructor. If it is less or equal to \p pMaxStack, the class will make
/// no memory allocation, and the array will be stored within the class, so it will be in the
/// stack (as long as the object is in the stack).
///
/// Otherwise, it will reserve the necessary memory dynamicaly.
///
/// \tparam tType the type of the objects to store
/// \tParam pMaxStack the maximum number of elements which will be stored in the stack.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
template<typename tType,std::size_t vAutoSize>
class CAutoVector
{
public:
    /// initializes the object to hold \p pSize elements
    
    /// If \p pSize>vAutoSize, then the memory will be allocated
    explicit CAutoVector(std::size_t pSize=0)
        :   mData(pSize>vAutoSize?new tType[pSize]:mAuto)
        ,   mSize(pSize)
    {}

    /// deletes any memory that might have been allocated
    ~CAutoVector()
    {
        if(mData!=mAuto)
            delete[] mData;
    }

    ///initializes the vector to a new size
    
    ///The contents will be discarded
    void Init(std::size_t pSize)
    {
        if(pSize>mSize)
        {
            if(mData!=mAuto)
            {
                delete[] mData;
                mData=new tType[pSize];
            }
            else if(pSize>vAutoSize)
            {
                mData=new tType[pSize];
            }
        }
        mSize=pSize;
    }
    
    std::size_t size() const     {   return mSize;   }
    
    /// returns a pointer to the array
    tType *data()
    {
        return mData;
    }

    /// returns a pointer to the array (const version)
    const tType *data() const
    {
        return mData;
    }

    /// returns a reference to an element
    tType &operator[](int i)
    {
        return mData[i];
    }

    /// returns a reference to an element (const version)
    const tType &operator[](int i) const
    {
        return mData[i];
    }

private:
    tType mAuto[vAutoSize];
    tType *mData;
    std::size_t mSize;
};

///@}

/*namespace buola*/ }

#endif
